#include "Socket.hpp"
#include "log.hpp"
#include <poll.h>
#include <unistd.h>

static const uint16_t DEFAULT_PORT = 8080; // 默认端口号
static const int fd_num_max = 64;

int default_fd = -1;
int no_event = 0;
class Poll
{
public:
    Poll(uint16_t port = DEFAULT_PORT) : _port(port)
    {
        _listen_fd = _listen_sock.Socket();
        _listen_sock.Bind(_listen_fd, _port);
        _listen_sock.Listen(_listen_fd);
        LogMessage(DEBUG, "SELECT INIT SUCCESS LISTEN_FD = %d", _listen_fd);
        for (int i = 0; i < fd_num_max; ++i)
        {
            _event_fds[i].fd = default_fd;
            _event_fds[i].events = no_event;
            _event_fds[i].revents = no_event;
        }
    }

    void Start()
    {
        _event_fds[0].fd = _listen_fd;
        _event_fds[0].events = POLLIN;
        int timeout = 3000;
        for (;;)
        {
            int n = poll(_event_fds, fd_num_max, timeout);
            switch (n)
            {
            case 0:
                LogMessage(DEBUG, "TIME OUT TIME:%d", timeout);
                sleep(1);
                break;
            case -1:
                LogMessage(DEBUG, "POLL FAIL");
                break;
            default:
                Dispatcher();
                break;
            }
        }
    }
    ~Poll()
    {
    }

private:
    // 事件分配器 poll 监听到有就绪的套接字 交给分配器处理
    void Dispatcher()
    {
        // 遍历准备就绪的文件描述符集合
        for (int i = 0; i < fd_num_max; ++i)
        {
            int fd = _event_fds[i].fd;
            if (fd == default_fd)
                continue;
            // 检查是否就绪
            if (_event_fds[i].events & POLLIN)
            {
                // 是否为监听套接字
                if (fd == _listen_fd)
                {
                    Accepter();
                }
                else
                {
                    Recver(fd, i);
                }
            }
        }
    }
    void Accepter()
    {

        std::string client_ip;
        uint16_t client_port;
        int sock = _listen_sock.Accept(_listen_fd, &client_ip, &client_port);
        if (sock < 0)
        {
            return;
        }
        LogMessage(NORMAL, "link success %s:%u", client_ip.c_str(), client_port);
        // 从_fd_array找到空位置存放新的套接字信息
        int pos = 1;
        for (; pos < fd_num_max; ++pos)
        {
            if (_event_fds[pos].fd != default_fd)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        // 满了 无法存放新连接的套接字
        if (pos == fd_num_max)
        {
            LogMessage(WARING, "SERVER IS FULL ,CLOSE SOCKET %d NOW", sock);
        }
        else
        {
            // 找到了空闲位置，存放新接受的套接字信息
            _event_fds[pos].fd = sock;
            _event_fds[pos].events = POLLIN;
            _event_fds[pos].revents = no_event;
            PrinfFd();
        }
    }
    void Recver(int fd, int pos)
    {
        char buffer[1024];
        ssize_t read_size = read(fd, buffer, sizeof(buffer - 1));
        if (read_size > 0)
        {
            buffer[read_size - 1] = '\0';
            std::cout << "ECHO# " << buffer << std::endl;
            sleep(1000);
        }
        else if (read_size == 0)
        {
            LogMessage(DEBUG, "CLIENT QUIT,CLOSE FD IS %d", fd);
            close(fd);
            _event_fds[pos].fd = default_fd;
        }
        else
        {
            LogMessage(DEBUG, "RECV ERROR,FD IS  %d", fd);
            close(fd);
            _event_fds[pos].fd = default_fd;
        }
    }
    void PrinfFd()
    {
        std::cout << "online fd list";
        for (int i = 0; i < fd_num_max; ++i)
        {
            if (_event_fds[i].fd == default_fd)
                continue;

            std::cout << _event_fds[i].fd << " ";
        }
    }

private:
    Sock _listen_sock;
    uint16_t _port;
    int _listen_fd;
    struct pollfd _event_fds[fd_num_max];
};